<template>
  <div id="web" class="web" />
</template>

<script>

export default {
  name: 'ThreeDWeb',
  components: {},
  props: {
    loadingVisible: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      dataModel: new ht.DataModel(),
      width: 450,
      height: 300,
      tall: 3,
      g3d: null,
      dm: null,
    }
  },
  computed: {},
  watch: {
    loadingVisible: {
      deep: true,
      immediate: true,
      handler(loadingVisible) {
        if (!loadingVisible) {
          this.$nextTick(() => {
            this.initModel()
          })
        }
      }
    }
  },
  created() {
  },
  mounted() {
  },
  methods: {
    createCommonNode(p3, s3) {
      const node = new ht.Node()
      // 分别设置位置，和大小，p3,s3分别是两个数组，
      node.p3(p3)
      node.s3(s3)
      return node
    },
    //
    initModel() {
      const { dataModel } = this
      const g3d = new ht.graph3d.Graph3dView(dataModel)// 3d 组件

      // this.dm.enableAnimation()
      g3d.setEye([-526, 169, 677])// 设置摄像头位置
      g3d.moveCamera([-389, 380, 1000], [-24, 110, 0], { duration: 1500 })

      const sky = this.createCommonNode([0, -130, 0], [20000, 20000, 20000]).s({
        'shape3d': 'sphere',
        // "shape3d.color": "#DDDDDD",
        'shape3d.reverse.flip': true,
        '2d.editable': false,
        '3d.editable': false,
        '2d.selectable': false,
        '3d.selectable': false,
        'shape3d.image': 'assets/htdesign/scene/skybox/vague_01.jpg'
      })
      g3d.setSkyBox(sky)

      // g3d.setFar(1e5)
      g3d.addToDOM()// 将 3d 组件添加进 body 中
      const that = this
      const { width, height, tall } = this

      // 声明图片（203行是图片的使用）
      ht.Default.setImage('panel', '/assets/htdesign/scene/skybox/vague_01.jpg')
      ht.Default.setImage('server', '/assets/server.png')

      ht.Default.setImage('alarm', {
        'width': 500,
        'height': 60,
        'comps': [
          {
            'type': 'rect',
            'rect': [50, 75, 20, 50],
            'background': {
              'value': 'gray',
              'func': 'attr@alarm.color'
            },
            'gradient': 'spread.horizontal'
          },
          {
            'type': 'triangle',
            'rect': [13, 5, 94, 84],
            'background': {
              'value': 'gray',
              'func': 'attr@alarm.color'
            }
          },
          {
            'type': 'circle',
            'rect': [49, 43, 21, 13],
            'background': 'rgba(255, 255, 255, 0.9)'
          },
          {
            'type': 'rect',
            'rect': [56, 59, 8, 22],
            'background': 'rgba(255, 255, 255, 0.9)'
          }
        ]
      })

      ht.Default.loadObj('/obj/pc.obj', '/obj/pc.mtl', { // 加载 obj 文件
        cube: true, // 是否将模型缩放到单位1的尺寸范围内，默认为false
        center: true, // 模型是否居中，默认为false，设置为true则会移动模型位置使其内容居中
        shape3d: 'pc', // 如果指定了shape3d名称，则HT将自动将加载解析后的所有材质模型构建成数组的方式，以该名称进行注册
        finishFunc: function(modelMap, array, rawS3) { // 用于加载后的回调处理
          // console.log(array);
          // console.log('rawS3:', rawS3);
          if (modelMap) {
            const formPane = that.createFormPane() // 创建form表单面板组件
            formPane.getView().className = 'formpane'// 设置form表单面板组件底层div的类名为formpane，用来设置样式和位置
            // const domPanel = document.getElementById('web')
            // domPanel.appendChild(formPane.getView())// 将form面板组件底层div添加进body中
            const x1 = 0
            const y1 = 200
            const z1 = 0

            const floor0 = that.create3DPlane([0, 400, 0], [width, tall, height], '业务产品')// 最上层
            // const pc1 = that.createNode('pc', floor0, '产品1', 1 )// 业务产品层内容
            // const pc2 = that.createNode('pc', floor0, '产品2', 2 )// 业务产品层内容
            // const pc3 = that.createNode('pc', floor0, '产品3', 3)// 业务产品层内容
            for (let i = 1; i < 4; i++) {
              const name = 'pc' + i
              window[name] = that.createRect(floor0, `产品${i}`, i)
            }
            // setIcon
            pc1.p3([-130, 440, z1])// 设置pc机的坐标
            pc2.p3([-10, 440, z1])// 设置pc机的坐标
            pc3.p3([90, 440, z1])// 设置pc机的坐标

            const floor1 = that.create3DPlane([x1, y1, z1], [width, tall, height], '逻辑系统')// 创建第一层的“地板”
            // const web1 = that.createNode('pc', floor1, '站点1', 4)// 创建第一层地板上的pc机
            // const web2 = that.createNode('pc', floor1, '站点2', 5)// 创建第一层地板上的pc机
            // const web3 = that.createNode('pc', floor1, '站点3', 6)// 创建第一层地板上的pc机
            // const web4 = that.createNode('pc', floor1, '站点4', 7)// 创建第一层地板上的pc机

            for (let i = 1; i <= 4; i++) {
              const name = 'web' + i
              window[name] = that.createRect(floor1, `站点${i}`, 3 + i)
            }

            web1.p3([x1 - 180, y1 + 35, z1 - 80])// 设置pc机的坐标
            web2.p3([x1 - 70, y1 + 35, z1 - 80])// 设置pc机的坐标
            web3.p3([x1 + 20, y1 + 35, z1 - 80])// 设置pc机的坐标
            web4.p3([x1 + 160, y1 + 35, z1 - 80])// 设置pc机的坐标

            // 连线
            window.line1 = that.createEdge(pc1, web1, 'green', 'line1')
            window.line2 = that.createEdge(pc1, web2, 'green')
            window.line3 = that.createEdge(pc2, web3, 'green', 'line3')
            window.line4 = that.createEdge(pc3, web4, 'green')

            // 闪烁动画
            // const colorAlarm = that.createAlarm(device1, formPane)// 创建一个告警节点
            // colorAlarm.setTag('colorAlarm')// 设置唯一标志tag
            // colorAlarm.blinkTimer = setTimeout(colorAlarm.blinkFunc, formPane.v('blinkInterval'))

            const x2 = 0; const y2 = 0; const z2 = 0
            const floor2 = that.create3DPlane([x2, y2, z2], [width, tall, height], '服务器')

            // 创建第二层中平行四边形以及梯形上方的四个节点
            for (let i = 1; i < 7; i++) {
              const name = 'rect' + i
              window[name] = that.createRect(floor1, `服务器${i}`, 11 + i)
            }
            // rgba(179,148,150,.2)

            // 设置第二层中平行四边形以及梯形上方的四个节点的位置
            const xAxis = x2
            // rect1.p3([xAxis - width * 0.5 * 0.3, y2 + 23, z2 - height * 0.2])
            rect1.p3([x1 - 150, y2 + 23, z2 - height * 0.2])
            rect2.p3([x1, y2 + 23, z2 - height * 0.2])
            rect3.p3([x1 + 150, y2 + 23, z2 - height * 0.2])
            rect4.p3([x1 - 150, y2 + 23, z2 + height * 0.2])
            rect5.p3([xAxis, y2 + 23, z2 + height * 0.2])
            rect6.p3([x1 + 150, y2 + 23, z2 + height * 0.2])

            // that.alarmFun(rect2, formPane)
            // that.alarmFun(rect6, formPane)

            // that.createPolyline(pc3, rect6)
            // 旋转动画
            const x3 = 0; const y3 = -200; const z3 = 0
            const floor3 = that.create3DPlane([x3, y3, z3], [width, tall, 400], '网络设备')

            // 创建第三层
            for (let i = 0; i < 2; i++) {
              const name = 'jhj' + i
              window[name] = that.createRect(floor3, `交换机${i + 1}`, 18 + i)
            }
            const x = 400; const y = 200; const angle = 360 / 8; const r = 120
            jhj0.p3([xAxis - 140, y2 - 180, z2 + height * 0.2])
            jhj1.p3([xAxis + 140, y2 - 180, z2 + height * 0.2])
            window.line5 = that.createEdge(jhj0, jhj1, 'green')

            // that.alarmFun(jhj1, formPane)

            window.line5 = that.createEdge(rect1, jhj0, 'green')
            window.line6 = that.createEdge(rect2, jhj0, 'green')
            window.line7 = that.createEdge(rect4, jhj0, 'green', 'line7')
            window.line8 = that.createEdge(rect5, jhj0, 'green')

            window.line18 = that.createEdge(rect3, jhj1, 'green')
            window.line19 = that.createEdge(rect6, jhj1, 'green')

            ht.Default.loadObj('/obj/机柜组件1.obj', '/obj/机柜组件1.mtl', {
              cube: true,
              center: true,
              shape3d: 'box',
              finishFunc: function(modelMap, array, rawS3) {
                if (modelMap) {
                  // window.device2 = that.createNode('box', floor1,'数据库1' ,8)
                  // window.device3 = that.createNode('box', floor1,'数据库2', 9)
                  // window.device4 = that.createNode('box', floor1,'数据库3', 10)
                  // window.database = that.createNode('box', floor1,'数据库4', 11)
                  for (let i = 1; i <= 4; i++) {
                    const deviceName = 'device' + (i + 1)
                    if (i <= 3) {
                      window[deviceName] = that.createRect(floor1, `数据库${i}`, 7 + i )
                    } else window.database = that.createRect(floor1, `数据库${i}`, 7 + i)
                  }
                  const arr = [window.device2, window.device3, window.device4, window.database]

                  console.log(arr)
                  arr.forEach(function(device, i) {
                    // device.s3(rawS3)
                    switch (i + 1) {
                      case 1:
                        window.line9 = that.createEdge(web1, device, 'green', 'line9')
                        break
                      case 2:
                        window.line10 = that.createEdge(web2, device, 'green')
                        break
                      case 3:
                        window.line11 = that.createEdge(web3, device, 'green', 'line11')
                        break
                      case 4:
                        window.line12 = that.createEdge(web4, device, 'green')
                        break
                    }
                  })

                  window.device2.p3([x1 - 160, y1 + 35, z1 + 120])
                  window.device3.p3([x1 - 70, y1 + 35, z1 + 120])
                  window.device4.p3([x1 + 20, y1 + 35, z1 + 120])
                  window.database.p3([x1 + 130, y1 + 35, z1 + 120])
                  // device4.p3([x1 + 240, y1 + 13, z1 + 60])

                  window.line13 = that.createEdge(window.device2, rect4, 'green', 'line13')
                  window.line14 = that.createEdge(window.device3, rect5, 'green')
                  window.line15 = that.createEdge(window.device4, rect6, 'green', 'line15')
                  window.line16 = that.createEdge(window.database, rect6, 'green')

                  that.alarmNode(formPane)
                }
              }
            })
            window.line17 = that.createEdge(web1, rect1, 'green')
            window.line21 = that.createEdge(web2, rect2, 'green')
            window.line22 = that.createEdge(web3, rect3, 'green')
            window.line20 = that.createEdge(web4, rect3, 'green')
          }
        }
      })


      this.clickEvent(g3d, this.createFormPane())
    },
    // 初次进来
    alarmNode(formPane) {
      const { dataModel } = this
      // 初次进来就高亮
      this.setEdgeColor(line3)
      this.setEdgeColor(line11)
      this.setEdgeColor(line15)
      // that.setEdgeColor(line19)
      // rect6.setStyle('shape3d.color', '#ff8a6c')

      this.alarmFun(rect6, formPane)
      const blinkTask = {
        interval: 1000,
        action: function(data) {
          const nodeType = data._styleMap.nodeType
          switch (nodeType) {
            case 2: // 产品2
            case 6: // 产品2
            case 10: // 产品2
            case 17: // 服务器6闪烁
            case 'line3':
            case 'line11':
            case 'line15':
              if (data.s('shape3d.color') === '#ff8a6c') {
                data.s('shape3d.color', '#7db798')
              } else {
                data.s('shape3d.color', '#ff8a6c')
              }
              break
          }
        }
      }
      dataModel.addScheduleTask(blinkTask)
    },

    // 绑定点击事件
    clickEvent(g3d, formPane) {
      const that = this
      // 绑定点击事件
      const eventType = ht.Default.isTouchable ? 'touchend' : 'mouseup';

      // g3d.onDataDoubleClicked = (data, e, part) => {
      //   if(data){
      //     const nodeType = data._styleMap.nodeType
      //     // console.log(nodeType)
      //     that.$emit('clickOnProductByThree', nodeType)
      //     switch (nodeType) {
      //       case 17: // 服务器4
      //         // todo：初次进来的不
      //         that.alarmNode(formPane)
      //         break
      //       case 18: // 交换机1
      //         break
      //     }
      //   }
      // }

      if (eventType === 'mouseup') {
        g3d.mi(function(t) {
          if (t.kind === 'doubleClickData') {
          //   if (t.data) {
          //     const nodeType = t.data._styleMap.nodeType
          //     // console.log(nodeType)
          //     that.$emit('clickOnProductByThree', nodeType)
          //     switch (nodeType) {
          //       case 17: // 服务器4
          //         // todo：初次进来的不
          //         that.alarmNode(formPane)
          //         break
          //       case 18: // 交换机1
          //         break
          //     }
          //   }
          }else if (t.kind === 'clickData') {
            // console.log(t.data)
            if (t.data) {
              const nodeType = t.data._styleMap.nodeType
              // console.log(nodeType)
              that.$emit('clickOnProductByThree', nodeType)
              switch (nodeType) {
                case 15: // 服务器4
                  that.setEdgeColor(line1, 'orange')
                  that.setEdgeColor(line9, 'orange')
                  that.setEdgeColor(line13, 'orange')
                  that.setEdgeColor(line7, 'orange')

                  const blinkTask = {
                    interval: 1000,
                    action: function(data) {
                      const nodeType = data._styleMap.nodeType
                      switch (nodeType) {
                        case 1:
                        case 4:
                        case 8:
                        case 15:
                        case 18:
                        case 'line1':
                        case 'line9':
                        case 'line13':
                        case 'line7':
                          if (data.s('shape3d.color') === '#86afff') {
                            data.s('shape3d.color', '#7db798')
                          } else {
                            data.s('shape3d.color', '#86afff')
                          }
                          break
                      }
                    }
                  }
                  // todo： 闪烁持续触发 // 恢复之前的错误闪烁
                  that.dataModel.removeScheduleTask(blinkTask)
                  that.dataModel.addScheduleTask(blinkTask)
                  break
                case 18: // 交换机1
                  break
              }
            }
            // nodeType
            // for (const e in link) t.data.getTag() === e && c(link[e])
          }
        })
      }
    },

    // 修改
    setEdgeColor(edge, color) {
      edge.setStyle('shape3d.color', color || 'red')
      edge.setStyle('edge.width', 3)
    },
    // 创建节点
    createNode(shape3d, host, label, nodeType, setImg, color) {
      const node = new ht.Node()
      node.s({
        'shape3d': shape3d,
        label,
        nodeType,
        // 'shape3d.image': 'panel',
        'label.offset.y': 1,
        'label.font': '10px arial, sans-serif',
        'label.color': color || '#0094ff',
        'label.position': 17,
        'label.transparent': true
      })
      node.setHost(host)
      this.dataModel.add(node)
      return node
    },

    // 创建连线
    createEdge(source, target, color, nodeType) {
      const edge = new ht.Edge()
      edge.s({
        'shape3d': 'cylinder',
        'edge.width': 1,
        nodeType,
        'shape3d.color': color || 'rgba(255,227,69,0.95)'
      })
      edge.setSource(source)// 设置起点
      edge.setTarget(target)// 设置终点

      this.dataModel.add(edge)
      return edge
    },

    // 创建小方块

    // setToolTip
    createRect(host, label, nodeType, bgColor, isSever) {
      // const { width, height } = this
      const shape = new ht.Node()
      shape.s3([60, 30, 30])
      shape.setHost(host)
      // 图片的使用
      //
      let params = {}
      if (isSever) {
        params = {
          'shape3d.image': 'server'
        }
      } else {
        params = {
          'shape3d.color': bgColor || '#7db798',
          // 'shape3d.color': '#7db798',
          label
        }
      }
      shape.s({
        'shape3d': 'rect',
        ...params,
        nodeType,
        'label.offset.y': 0,
        'label.font': '14px arial, sans-serif',
        'label.color': '#fff',
        'label.position': 17,
        'label.transparent': true// 文字在3D下是否透明，实际上是指的文字的边框，这样字体周边就没有锯齿了
      })
      this.dataModel.add(shape)

      shape.setToolTip('I love HT')
      return shape
    },
    // 闪烁
    alarmFun(device, formPane) {
      const rotateAlarm = this.createAlarm(device, formPane)
      rotateAlarm.setTag('rotateAlarm')
      rotateAlarm.rotateTimer = setTimeout(rotateAlarm.rotateFunc, formPane.v('rotInterval'))
    },
    // 创建底部平面
    create3DPlane(p3, s3, label, color) {
      const node = new ht.Node()
      node.p3(p3)
      node.s3(s3)
      // shape2.setStyle("shape.background", null);
      // shape2.setStyle("shape.border.width", 10);
      // shape2.setStyle("shape.border.color", "#1ABC9C");
      node.s({
        'shape3d': 'rect',
        'label': label,
        'label.offset.y': 30,
        'label.font': '18px arial, sans-serif',
        'label.color': '#fff',
        'label.position': 30,
        'shape3d.color': color || 'rgb(1,10,27,.7)'
        // 'shape3d.image': 'panel',
      })
      this.dataModel.add(node)
      return node
    },

    // 创建“警告”标识
    createAlarm(device, formPane) {
      const ringModel = ht.Default.createRingModel([8, 1, 0, 1, 10, -1, 8, -1, 8, 1], null, null, false, false, 600)// 根据xy平面的曲线，环绕一周形成3D模型。
      const sphereModel = ht.Default.createSmoothSphereModel(8, 8, 0, Math.PI * 2, 0, Math.PI, 2)// 构建光滑球体模型
      const cylinderModel = ht.Default.createSmoothCylinderModel(8, true, true, 1, 2, 0, Math.PI * 2, 8)// 构建光滑圆柱体模型

      const alarmArr = [// 组合模型 由三个模型ringModel、sphereModel、cylinderModel组合而成
        {
          shape3d: ringModel, // 定义模型类型
          r3: [Math.PI / 2, 0, 0], // 设置旋转角度
          color: { // 设置模型颜色
            func: 'style@all.blend'// 数据绑定style样式中的all.blend属性，可通过data.s()获取和设置这个属性
          }
        }, {
          shape3d: sphereModel,
          t3: [0, 4, 0],
          color: {
            func: 'style@all.blend'
          }
        }, {
          shape3d: cylinderModel,
          t3: [0, -3, 0],
          color: {
            func: 'style@all.blend'
          }
        }
      ]
      ht.Default.setShape3dModel('alarm', { // 注册自定义3D模型
        shape3d: alarmArr
      })

      const alarmNode = this.createNode('alarm', device)// 创建shape3d为alarm的节点
      alarmNode.s3([2, 2, 2])// 设置节点大小
      alarmNode.p3(device.p3()[0], device.p3()[1] + 60, device.p3()[2])
      alarmNode.s('all.blend', 'red')// 改变此属性可改变模型的颜色，因为模型创建的时候已经数据绑定了

      if (formPane) {
        alarmNode.scaleFunc = function() {
          const size = alarmNode.s3()
          if (size[0] === 2 && size[1] === 2 && size[2] === 2) alarmNode.s3([1, 1, 1])
          else alarmNode.s3([2, 2, 2])
          alarmNode.scaleTimer = setTimeout(alarmNode.scaleFunc, formPane.v('scaleInterval'))
        }
        alarmNode.blinkFunc = function() {
          const color = alarmNode.s('all.blend')
          if (color === 'red') alarmNode.s({ 'all.blend': 'yellow' })
          else alarmNode.s({ 'all.blend': 'red' })
          alarmNode.blinkTimer = setTimeout(alarmNode.blinkFunc, formPane.v('blinkInterval'))
        }
        alarmNode.rotateFunc = function() {
          alarmNode.setRotation(alarmNode.getRotation() + Math.PI / 20)
          alarmNode.rotateTimer = setTimeout(alarmNode.rotateFunc, formPane.v('rotInterval'))
        }
      }

      return alarmNode
    },

    // 创建表单的行
    createFormPane() {
      const formPane = new ht.widget.FormPane()
      formPane.setWidth(250)
      formPane.setHeight(120)
      formPane.setRowHeight(30)
      formPane.addRow([
        {
          checkBox: {
            label: 'Enable Blink',
            selected: true,
            onValueChanged: function() {
              const data = this.dataModel.getDataByTag('colorAlarm')
              if (this.getValue()) {
                data.blinkTimer = setTimeout(data.blinkFunc, formPane.v('blinkInterval'))
              } else {
                clearTimeout(data.blinkTimer)
              }
            }
          }
        },
        {
          id: 'blinkInterval',
          slider: {
            min: 0,
            max: 1000,
            step: 50,
            value: 500
          }
        }
      ], [0.1, 0.1])
      formPane.addRow([
        {
          checkBox: {
            label: 'Enable Scale',
            selected: true,
            onValueChanged: function() {
              const data = this.dataModel.getDataByTag('scaleAlarm')
              if (this.getValue()) {
                data.scaleTimer = setTimeout(data.scaleFunc, formPane.v('scaleInterval'))
              } else {
                clearTimeout(this.dataModel.getDataByTag('scaleAlarm').scaleTimer)
              }
            }
          }
        },
        {
          id: 'scaleInterval',
          slider: {
            min: 0,
            max: 1000,
            step: 50,
            value: 500
          }
        }
      ], [0.1, 0.1])
      formPane.addRow([
        {
          checkBox: {
            label: 'Enable Rotation',
            selected: true,
            onValueChanged: function() {
              const data = this.dataModel.getDataByTag('rotateAlarm')
              if (this.getValue()) {
                data.rotateTimer = setTimeout(data.rotateFunc, formPane.v('rotInterval'))
              } else {
                clearTimeout(data.rotateTimer)
              }
            }
          }
        },
        {
          id: 'rotInterval',
          slider: {
            min: 0,
            max: 300,
            step: 20,
            value: 50
          }
        }
      ], [0.1, 0.1])
      return formPane
    }
  }
}
</script>

<style scoped lang='scss'>
  .web{
    width: 100%;
    height: 100vh;
    position: relative;
  }
  .formpane {
    top: 10px;
    right: 10px;
    background: rgba(255, 255, 255, 0.85);
  }
</style>
